package com.ych.modules.common.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.ych.SDK.alibaba.ossSDK.AliOssUtil;
import com.ych.modules.api.authorInfc.item.entity.AuditItemBiddingEntity;
import com.ych.modules.api.authorInfc.jackpot.service.JackpotService;
import com.ych.modules.base.dbEntity.*;
import com.ych.modules.base.service.*;
import com.ych.modules.common.entity.query.QueryConcernItemEntity;
import com.ych.modules.common.entity.query.QueryUserItemEntity;
import com.ych.modules.common.service.UserItemService;
import com.ych.utils.TLMap;
import com.ych.utils.UUID;
import com.ych.utils.beanToMap.BeanMapUtil;
import com.ych.utils.mysqlPageUtil.Query;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.util.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;


/**
 * Created with IntelliJ IDEA.
 * Author: Usopp.tsui
 * Date: 2021/1/2
 * Time: 11:20
 * Description:
 */
@Service("UserItemService")
public class UserItemServiceImpl implements UserItemService {
    @Autowired
    private ITUserItemService          itUserItemService;
    @Autowired
    private AliOssUtil                 aliOssUtil;
    @Autowired
    private ITSysImgService            itSysImgService;
    @Autowired
    private ITItemLikeService          itItemLikeService;
    @Autowired
    private ITItemConcernService       itItemConcernService;
    @Autowired
    private ITUserAccountService       itUserAccountService;
    @Autowired
    private ITItemBiddingService       itItemBiddingService;
    @Autowired
    private ITUserAccountChangeService itUserAccountChangeService;
    @Autowired
    private JackpotService             jackpotService;
    @Autowired
    private ITUserInfoService          itUserInfoService;

    @Override
    public TUserItemEntity getUserItem(String itemId) {
        TUserItemEntity itemEntity = itUserItemService.selectById(itemId);
        if (null == itemEntity) {
            throw new RuntimeException("项目不存在！");
        }
        //扩展项目图片
        this.extendsItemImg(itemEntity);
        //扩展项目点赞数，关注数
        this.extendsItemLikeConcernCount(itemEntity);
        //扩展当前用户是否关注/点赞
        this.extendsUserLikeConcern(itemEntity);
        //扩展发布者信息
        this.extendsCreateUserInfo(itemEntity);
        //浏览次数自增1
        this.itemViewCountIncrement(itemId);
        return itemEntity;
    }

    /**
     * 判断当前用户是否关注/点赞
     *
     * @param itemEntity
     */
    private void extendsUserLikeConcern(TUserItemEntity itemEntity) {
        //点赞
        Wrapper<TItemLikeEntity> likeWrapper = new EntityWrapper<TItemLikeEntity>()
                .where("1=1")
                .eq("item_id", itemEntity.getItemId())
                .eq("user_id", TLMap.getUserId());
        Integer likeCount = itItemLikeService.selectCount(likeWrapper);
        if (likeCount > 0) {
            itemEntity.setIsLike("0");
        }
        //关注
        Wrapper<TItemConcernEntity> concernWrapper = new EntityWrapper<TItemConcernEntity>()
                .where("1=1")
                .eq("item_id", itemEntity.getItemId())
                .eq("user_id", TLMap.getUserId());
        Integer concernCount = itItemConcernService.selectCount(concernWrapper);
        if (concernCount > 0) {
            itemEntity.setIsConcern("0");
        }
    }

    /**
     * 扩展项目点赞数，关注数
     *
     * @param itemEntity
     */
    private void extendsItemLikeConcernCount(TUserItemEntity itemEntity) {
        //点赞数量
        Wrapper<TItemLikeEntity> likeWrapper = new EntityWrapper<TItemLikeEntity>()
                .where("1=1")
                .eq("item_id", itemEntity.getItemId());
        Integer likeCount = itItemLikeService.selectCount(likeWrapper);
        itemEntity.setLikeCount(likeCount);
        //关注数量
        Wrapper<TItemConcernEntity> concernWrapper = new EntityWrapper<TItemConcernEntity>()
                .where("1=1")
                .eq("item_id", itemEntity.getItemId());
        Integer concernCount = itItemConcernService.selectCount(concernWrapper);
        //数量相等就算了，不相等就更新一下最新的
        if (concernCount != itemEntity.getConcernCount()) {
            itemEntity.setConcernCount(concernCount);
            itUserItemService.updateById(itemEntity);
        }
    }

    @Override
    public Page<TUserItemEntity> listUserItem(QueryUserItemEntity entity) {
        Wrapper<TUserItemEntity> wrapper = new EntityWrapper<TUserItemEntity>()
                .where("1=1")
                .eq(StringUtils.isNotBlank(entity.getUserId()), "user_id", entity.getUserId())
                .eq(StringUtils.isNotBlank(entity.getItemType()), "item_type", entity.getItemType())
                .eq(StringUtils.isNotBlank(entity.getMobile()), "mobile", entity.getMobile())
                .eq(StringUtils.isNotBlank(entity.getStatus()), "status", entity.getStatus())
                .like(StringUtils.isNotBlank(entity.getItemName()), "item_name", entity.getItemName());
        if (StringUtils.isNotBlank(entity.getOrderType())) {
            switch (entity.getOrderType()) {
                case "0"://时间排序
                    wrapper.orderBy("create_time desc");
                    break;
                case "1"://热度排序
                    wrapper.orderBy("view_count desc");
                    break;
                case "2"://关注度排序
                    wrapper.orderBy("concern_count desc");
                    break;
                default:
                    break;
            }
        }
        Page<TUserItemEntity> page = itUserItemService.selectPage(new Query<TUserItemEntity>(BeanMapUtil.toPageQuery(entity)).getPage(), wrapper);
        List<TUserItemEntity> list = new ArrayList<>();
        for (TUserItemEntity itemEntity : page.getRecords()) {
            //扩展项目图片
            this.extendsItemImg(itemEntity);
            list.add(itemEntity);
            this.extendsCreateUserInfo(itemEntity);//扩展发布者信息
        }
        page.setRecords(list);
        return page;
    }

    /**
     * 扩展发布用户信息
     *
     * @param itemEntity
     */
    private void extendsCreateUserInfo(TUserItemEntity itemEntity) {
        //扩展发布者信息
        TUserInfoEntity userInfoEntity = itUserInfoService.selectById(itemEntity.getUserId());
        itemEntity.setUserName(userInfoEntity.getUserName());
        itemEntity.setUserHeadUrl(aliOssUtil.getOssObjectDownAuthUrl(userInfoEntity.getUserHeadUrl()));
    }

    /**
     * 扩展项目图片
     *
     * @param itemEntity
     */
    private void extendsItemImg(TUserItemEntity itemEntity) {
        List<String> detailImgList = this.listImgs(itemEntity.getItemId(), "10008003");
        if (!CollectionUtils.isEmpty(detailImgList)) {
            itemEntity.setDetailImgList(detailImgList);
        }
        List<String> headImg = this.listImgs(itemEntity.getItemId(), "10008002");
        if (!CollectionUtils.isEmpty(headImg)) {
            itemEntity.setHeadImg(headImg.get(0));
        }
    }

    /**
     * 获取图片列表
     *
     * @param itemId
     * @param imgType
     * @return
     */
    private List<String> listImgs(String itemId, String imgType) {
        Wrapper<TSysImgEntity> wrapper = new EntityWrapper<TSysImgEntity>()
                .where("1=1")
                .eq("business_id", itemId)
                .eq("img_type", imgType)
                .orderBy("img_sequence asc");
        List<TSysImgEntity> imgEntityList = itSysImgService.selectList(wrapper);
        if (CollectionUtils.isEmpty(imgEntityList)) {
            return null;
        }
        List<String> resultList = new ArrayList<>();
        for (TSysImgEntity entity : imgEntityList) {
            resultList.add(aliOssUtil.getOssObjectDownAuthUrl(entity.getImgUrl()));
        }
        return resultList;
    }

    @Override
    public void negation(String itemId) {
        TUserItemEntity itemEntity = itUserItemService.selectById(itemId);
        if (null == itemEntity) {
            throw new RuntimeException("项目不存在！");
        }
        //取反
        itemEntity.setStatus("0".equals(itemEntity.getStatus()) ? "1" : "0");
        itUserItemService.updateById(itemEntity);
    }

    @Override
    @Transactional(isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void createItem(TUserItemEntity itemEntity) {
        //校验账户金币余额
        this.validateAccountCoinAmount(itemEntity.getPayAmount());
        itemEntity.setItemId(UUID.randomUUID());
        itemEntity.setCreateTime(new Date());
        itemEntity.setViewCount(0);
        itemEntity.setStatus("0");
        itemEntity.setRechargeStatusType("10003002");//交易成功
        itemEntity.setItemStatusType("10007002");//待审核
        itemEntity.setMobile(TLMap.getMobile());
        //头图处理
        if (StringUtils.isNotBlank(itemEntity.getHeadImg())) {
            this.addImg(itemEntity.getHeadImg(), itemEntity.getItemId(), 1, "10008002");
        }
        //详情图处理
        if (!CollectionUtils.isEmpty(itemEntity.getDetailImgList())) {
            for (int i = 0; i < itemEntity.getDetailImgList().size(); i++) {
                this.addImg(itemEntity.getDetailImgList().get(i)
                        , itemEntity.getItemId()
                        , i, "10008003");
            }
        }
        List<String> tagList = itemEntity.getItemTagTypeList();
        //标签处理
        if (null != tagList && tagList.size() > 0) {
            if (tagList.size() > 2) {
                throw new RuntimeException("最多只能设置两个标签！");
            }
            itemEntity.setItemTagType(String.join(",", tagList));
        }
        itUserItemService.insert(itemEntity);
        //减去账户金币数量
        itUserAccountService.alterGoldCoinAmount("10000002", "10001004", TLMap.getUserId(), itemEntity.getItemId(), itemEntity.getPayAmount());
        //将金币按比例写入奖池
        try {
            //支付金额就是要分到奖池的金额
            BigDecimal amount = itemEntity.getPayAmount();
            //10012001：项目发布
            jackpotService.addAmountToJackpot("10012001", amount, itemEntity.getItemId(), null);
        } catch (Exception e) {
            //不阻断正常流程
        }
    }

    /**
     * 校验账户金币余额是否足以购买项目
     *
     * @param payAmount
     */
    private void validateAccountCoinAmount(BigDecimal payAmount) {
        TUserAccountEntity accountEntity = itUserAccountService.selectById(TLMap.getUserId());
        if (payAmount.compareTo(accountEntity.getGoldCoinAmount()) == 1) {
            throw new RuntimeException("账户金币余额不足，请先购置金币");
        }
    }

    /**
     * 添加图片实体
     *
     * @param imgUrl
     * @param businessId
     * @param imgSequence
     * @param imgType
     */
    private void addImg(String imgUrl, String businessId, int imgSequence, String imgType) {
        TSysImgEntity entity = new TSysImgEntity();
        entity.setImgId(UUID.randomUUID());
        entity.setImgUrl(aliOssUtil.getRelativePath(imgUrl));
        entity.setImgType(imgType);
        entity.setBusinessId(businessId);
        entity.setImgSequence(imgSequence);
        entity.setCreate_time(new Date());
        itSysImgService.insert(entity);
    }

    @Override
    public void itemViewCountIncrement(String itemId) {
        try {
            TUserItemEntity itemEntity = itUserItemService.selectById(itemId);
            TUserItemEntity tempEntity = new TUserItemEntity();
            tempEntity.setItemId(itemId);
            tempEntity.setViewCount(itemEntity.getViewCount() + 1);
            itUserItemService.updateById(tempEntity);
        } catch (Exception e) {
            //有异常也不处理,大不了不要这一次记录了,不影响程序运行
        }
    }

    @Override
    public void likeItem(String itemId) {
        TUserItemEntity entity = itUserItemService.selectById(itemId);
        if (null == entity) {
            throw new RuntimeException("所选项目不存在");
        }
        //判断是否已经点赞过了，点过了就取消点赞
        Wrapper<TItemLikeEntity> wrapper = new EntityWrapper<TItemLikeEntity>()
                .where("1=1")
                .eq("user_id", TLMap.getUserId())
                .eq("item_id", itemId);
        TItemLikeEntity itemLikeEntity = itItemLikeService.selectOne(wrapper);
        if (null != itemLikeEntity) {
            //删除这个点赞
            itItemLikeService.deleteById(itemLikeEntity.getId());
            return;
        }
        //添加点赞
        TItemLikeEntity likeEntity = new TItemLikeEntity();
        likeEntity.setId(UUID.randomUUID());
        likeEntity.setItemId(itemId);
        likeEntity.setUserId(TLMap.getUserId());
        likeEntity.setCreateTime(new Date());
        itItemLikeService.insert(likeEntity);
    }

    @Override
    public void concernItem(String itemId) {
        TUserItemEntity entity = itUserItemService.selectById(itemId);
        if (null == entity) {
            throw new RuntimeException("所选项目不存在");
        }
        //判断是否已经关注过了，点过了就取消关注
        Wrapper<TItemConcernEntity> wrapper = new EntityWrapper<TItemConcernEntity>()
                .where("1=1")
                .eq("user_id", TLMap.getUserId())
                .eq("item_id", itemId);
        TItemConcernEntity itemConcernEntity = itItemConcernService.selectOne(wrapper);
        if (null != itemConcernEntity) {
            //删除这个关注
            itItemConcernService.deleteById(itemConcernEntity.getId());
            return;
        }
        //添加关注
        TItemConcernEntity concernEntity = new TItemConcernEntity();
        concernEntity.setId(UUID.randomUUID());
        concernEntity.setItemId(itemId);
        concernEntity.setUserId(TLMap.getUserId());
        concernEntity.setCreateTime(new Date());
        itItemConcernService.insert(concernEntity);
    }

    @Override
    @Transactional(isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void biddingItem(TItemBiddingEntity entity) {
        TUserItemEntity itemEntity = itUserItemService.selectById(entity.getItemId());
        if (null == itemEntity) {
            throw new RuntimeException("竞价项目不存在");
        }
        TUserAccountEntity accountEntity = itUserAccountService.selectById(TLMap.getUserId());
        if (null == accountEntity) {
            throw new RuntimeException("用户账户异常，请联系系统管理员");
        }
        if (accountEntity.getGoldCoinAmount().compareTo(entity.getGoldCoinAmount()) == -1) {
            throw new RuntimeException("金币余额不足");
        }
        //存一份金额
        BigDecimal goldCoin = entity.getGoldCoinAmount();
        //判断是否竞价过了，参与过竞价则这次进行累加
        TItemBiddingEntity biddingEntity = this.getCurrentBiddingInfo(entity.getItemId());
        if (null == biddingEntity) {
            entity.setBiddingId(UUID.randomUUID());
            entity.setCreateTime(new Date());
            entity.setUserId(TLMap.getUserId());
            itItemBiddingService.insert(entity);
        } else {
            entity.setBiddingId(biddingEntity.getBiddingId());
            entity.setGoldCoinAmount(biddingEntity.getGoldCoinAmount().add(goldCoin));
            itItemBiddingService.updateById(entity);
        }
        //将金额设置回去，避免账户多扣除
        entity.setGoldCoinAmount(goldCoin);
        //添加账户变更记录
        this.addGoldCoinChangeInfo(entity);
        //用户账户金币金额减去
        TUserAccountEntity tempAccountEntity = new TUserAccountEntity();
        tempAccountEntity.setUserId(TLMap.getUserId());
        tempAccountEntity.setGoldCoinAmount(goldCoin.negate());
        itUserAccountService.updateByEntity(tempAccountEntity);
    }

    /**
     * 获取当前用户已经参加了此次竞价的竞价实体
     *
     * @return
     */
    private TItemBiddingEntity getCurrentBiddingInfo(String itemId) {
        Wrapper<TItemBiddingEntity> wrapper = new EntityWrapper<TItemBiddingEntity>()
                .where("1=1")
                .eq("item_id", itemId)
                .eq("user_id", TLMap.getUserId());
        return itItemBiddingService.selectOne(wrapper);
    }

    @Override
    public Page<TItemBiddingEntity> listItemBidding(TItemBiddingEntity entity) {
        TUserItemEntity itemEntity = itUserItemService.selectById(entity.getItemId());
        if (null == itemEntity) {
            throw new RuntimeException("项目不存在！");
        }
        Wrapper<TItemBiddingEntity> wrapper = new EntityWrapper<TItemBiddingEntity>()
                .where("1=1")
                .eq("item_id", entity.getItemId())
                .eq(StringUtils.isNotBlank(entity.getBiddingType()), "bidding_type", entity.getBiddingType())//竞价中的
                .orderBy("gold_coin_amount desc")
                .orderBy("create_time asc");
        Page<TItemBiddingEntity> page = itItemBiddingService.selectPage(new Query<TItemBiddingEntity>(BeanMapUtil.toPageQuery(entity)).getPage(), wrapper);
        for (int i = 0; i < page.getRecords().size(); i++) {
            TItemBiddingEntity biddingEntity = page.getRecords().get(i);
            TUserInfoEntity userInfoEntity = itUserInfoService.selectById(biddingEntity.getUserId());
            biddingEntity.setUserName(userInfoEntity.getUserName());
            biddingEntity.setUserHeadUrl(aliOssUtil.getOssObjectDownAuthUrl(userInfoEntity.getUserHeadUrl()));
            //处理竞价排序的第一个数据
            if (i == 0) {
                biddingEntity.setMobile(userInfoEntity.getMobile());
            }
        }
        return page;
    }

    @Override
    public void removeItem(String itemId) {
        TUserItemEntity itemEntity = itUserItemService.selectById(itemId);
        if (null == itemEntity) {
            throw new RuntimeException("目标项目不存在");
        }
        TUserItemEntity tempItem = new TUserItemEntity();
        tempItem.setItemId(itemId);
        tempItem.setStatus("1");//删除
        itUserItemService.updateById(tempItem);
    }

    @Override
    public Page<TUserItemEntity> listConcernItem(QueryConcernItemEntity entity) {
        Wrapper<TItemConcernEntity> wrapper = new EntityWrapper<TItemConcernEntity>()
                .where("1=1")
                .eq("user_id", entity.getUserId())
                .setSqlSelect("item_id as itemId");
        List<Map<String, Object>> concernItemList = itItemConcernService.selectMaps(wrapper);
        List<String> itemIdList = new ArrayList<>();
        for (Map<String, Object> map : concernItemList) {
            itemIdList.add((String) map.get("itemId"));
        }
        Wrapper<TUserItemEntity> itemWrapper = new EntityWrapper<TUserItemEntity>()
                .where("1=1")
                .eq("status", "0")
                .in("item_id", itemIdList);
        Page<TUserItemEntity> page = itUserItemService.selectPage(new Query<TUserItemEntity>(BeanMapUtil.toPageQuery(entity)).getPage(), itemWrapper);
        for (TUserItemEntity itemEntity : page.getRecords()) {
            //扩展项目图片
            this.extendsItemImg(itemEntity);
            //扩展当前用户是否关注/点赞
            this.extendsUserLikeConcern(itemEntity);
        }
        return page;
    }

    @Override
    @Transactional(isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void auditItemBidding(AuditItemBiddingEntity vo) {
        TItemBiddingEntity biddingEntity = itItemBiddingService.selectById(vo.getBiddingId());
        if (null == biddingEntity) {
            throw new RuntimeException("竞价不存在");
        }
        if (!"10017001".equals(biddingEntity.getBiddingType())) {
            throw new RuntimeException("已完成竞价，请勿重复操作");
        }
        TUserItemEntity itemEntity = itUserItemService.selectById(biddingEntity.getItemId());
        //不为admin也不为项目发布者
        if (!"1".equals(TLMap.getUserId())
                && !itemEntity.getUserId().equals(TLMap.getUserId())) {
            throw new RuntimeException("非法请求，这不是你的项目");
        }
        switch (vo.getBiddingType()) {
            case "10017002"://竞价成功
                biddingEntity.setBiddingType("10017002");
                //处理成功竞价
                this.dealSuccessBidding(biddingEntity, itemEntity);
                break;
            case "10017003"://竞价失败
                biddingEntity.setBiddingType("10017003");
                //处理失败竞价
                this.dealFailBidding(biddingEntity, itemEntity);
                break;
            default:
                throw new RuntimeException("未知审核类型");
        }
        itItemBiddingService.updateById(biddingEntity);
    }

    /**
     * 处理失败竞价
     *
     * @param biddingEntity
     * @param itemEntity
     */
    private void dealFailBidding(TItemBiddingEntity biddingEntity, TUserItemEntity itemEntity) {
        //竞价失败，全额退还给发起竞价的用户
        itUserAccountService.alterGoldCoinAmount("10000001", "10001002", biddingEntity.getUserId(), biddingEntity.getBiddingId(), biddingEntity.getGoldCoinAmount());
    }

    /**
     * 处理成功竞价
     *
     * @param biddingEntity
     */
    private void dealSuccessBidding(TItemBiddingEntity biddingEntity, TUserItemEntity itemEntity) {
        BigDecimal amount = biddingEntity.getGoldCoinAmount()
                .multiply(new BigDecimal("0.8"));//百分之八十给项目发布者，百分之二十给平台
        itUserAccountService.alterGoldCoinAmount("10000001", "10001002", itemEntity.getUserId(), biddingEntity.getBiddingId(), amount);
    }

    /**
     * 添加金币变更记录
     *
     * @param entity 竞价实体
     */
    private void addGoldCoinChangeInfo(TItemBiddingEntity entity) {
        TUserAccountEntity accountEntity = itUserAccountService.selectById(TLMap.getUserId());
        TUserAccountChangeEntity changeEntity = new TUserAccountChangeEntity();
        changeEntity.setChangeId(UUID.randomUUID());
        changeEntity.setUserId(TLMap.getUserId());
        changeEntity.setAccountTrend("10000002");//支出
        changeEntity.setBusinessId(entity.getBiddingId());
        changeEntity.setAccountChangeBusinessType("10001002");//项目竞价订单
        //现金
        changeEntity.setCashAmount(BigDecimal.ZERO);
        changeEntity.setBeforeCashAmount(accountEntity.getCashAmount());
        changeEntity.setAfterCashAmount(accountEntity.getCashAmount());
        //金币
        changeEntity.setGoldCoinAmount(entity.getGoldCoinAmount());
        changeEntity.setBeforeGoldCoinAmount(accountEntity.getGoldCoinAmount());
        changeEntity.setAfterGoldCoinAmount(accountEntity.getGoldCoinAmount().subtract(entity.getGoldCoinAmount()));
        //抽奖券
        changeEntity.setRaffleTicket(0);
        changeEntity.setBeforeRaffleTicket(accountEntity.getRaffleTicket());
        changeEntity.setAfterRaffleTicket(accountEntity.getRaffleTicket());
        changeEntity.setCreateTime(new Date());
        itUserAccountChangeService.insert(changeEntity);
    }
}
